<?

/*
Form Class

@author		Jelle Versele
@email 		me@jelleversele.be

*/



// required files 

require_once('view/htmlTag.class.php');
require_once('form/group.class.php');


// begin class 

class form{
	/*
		@const	standaard decorator
	*/
	const DECORATOR_BASIC = 'basic';
	/*
		@const	encoding type
	*/
	const MULTIPART_FRM_DATA = 'multipart/form-data';
	/*
		@const	encoding type
	*/
	const TEXT_PLAIN = 'text/plain';

	/*
		@const	POST moet gebruikt worden om de methode in te stellen
	*/
	const POST = 'POST';
	/*
		@const	idem als hierboven
	*/
	const GET = 'GET';
	/*
		@const	prefix voor de class string aan te maken
	*/
	const classPrefix = 'form_element_';
	/*
		@const	prefix voor de decorator string aan te maken
	*/
	const decoratorPrefix = 'form_decorator_';
	/*
		@const	prefix voor de filestring naar de class
	*/
	const filePrefix = 'form/element/';
	/*
		@const	suffix voor de class string aan te maken
	*/
	const fileSuffix = '.class.php';
	/*
		@const	element type definieren
	*/
	const elementType = 'form_element';
	/*
		@const	prefix voor de class string aan te maken
	*/
	const groupType = 'form_group';
	/*
		@var	obj form_decorator_ ...
	*/
	private $decorator;
	/*
		@var	array
	*/
	private $elements;
	/*
		@var	string
	*/
	private $name;
	/*
		@var	string
	*/
	private $method;
	/*
		@var	obj
	*/
	private $submitButton;
	/*
		@var	array
	*/
	private $groups;
	/*
		@var	string
	*/
	private $enctype;
	
	/*
		@var	string
	*/
	private $action;

		
	/*
		Een Form object initialiseren
		
		@param		iName		string
		@param 		iMehtod		form::POST OR form::GET
		
	*/
	public function __construct($iName, $iMethod, $iDecorator = NULL, $iAction = NULL){
	
		$this -> groups = array();
		$this -> elements = array();
		$this -> name = $iName;
		
		if(isset($iDecorator)){
			$this -> decorator = $iDecorator;
		}else{
			$this -> decorator = self::DECORATOR_BASIC;
		}
		
		if($iMethod == self::POST || $iMethod == self::GET){
		
			$this -> method = (string) $iMethod;
		
		}else{
			throw new Exception("Method is not valid. Use get or post.");
		}
		
		
		$this -> action = $iAction;
		
	}
	
	/*
		@method		array		geeft alle ellementen van het formulier terug
	*/
	
	public function getElements(){
		return $this -> elements;
	}
	
	/*
		@Method		bool		controleert of het formulier verzonden is 
	*/
	
	public function isSend(){
	
		if($_SERVER['REQUEST_METHOD'] == $this -> method){
		
			if(isset($this -> submitButton)){ 
				if($this -> submitButton -> getSend()){
					return true;
				}
			}else{
				return true;
			}
		
		}else{
		
			return false;
		
		}
	}
	
	/*
		@method		nothing		set de submitbutton
		@param		obj			object moet van het type form_element zijn	
	*/
	
	public function setToSubmit(form_element $iBtn){

		if($this -> checkElementType($iBtn) && $this -> elementExists($iBtn->getName())){
			$this -> submitButton = (object) $iBtn;
		}else{
			throw new Exception("cannot find element in form class OR element type is not valid. All form elements must extend form_element");
		}
	
	}
	
	/*
		@method		object/form_element		maakt een form_element aan 
		@param		iName	string			naam v/h object
		@param		iType	string			type v/h object
	*/
	
	public function createElement($iName, $iType){
		
		$class 	= self::classPrefix.$iType;
		$file 	= get_include_path().self::filePrefix.$iType.self::fileSuffix;
		
	
		if(is_file($file)){
			
			require_once($file);
			
			if(class_exists($class)){
		
				$element = new $class($iName);
				return $element;
			
			}else{
		
			throw new Exception("form element <strong>".$iType."</strong> doesn't exists!");
			
			}
		}else{
		
			throw new Exception("form element <strong>".$iType."</strong> doesn't exists!");
			
		}
		
	}
	
	/*
	 *	@method		nothin		voegt formulier elementen toe aan de het formobject 
	 *	@param 		iElement	obj
	*/
	
	public function addElement($iElement){
		
		if($this -> checkElementType($iElement) && !$this -> elementExists($iElement)){
			
			if(get_class($iElement) == 'form_element_fileField'){
			
				$this -> setEncType(self::MULTIPART_FRM_DATA);
			
			}
			
			
			if(get_parent_class($iElement) == self::elementType){
			
				$iElement -> setMethod($this -> method);
			
			}
			
			$this -> elements[$iElement -> getName()] = (object) $iElement;
			
		}else{
			throw new Exception("object name already exists OR form element is not of type FORM_ELEMENT");
		}
	}
	
	public function addElementRange(array $iElements){
	
		foreach($iElements as $element){
		
			$this -> addElement($element);
		
		}
	
	}
	
	
	/*
	 *	@method		nothing		geeft een niewe form group terug en voegt elementen toe aan dit object 
	 *	@param		iName		string	
	 *	@param		iType		string	type group as html tag	
	*/
	public function createGroup($iName, $iType){
		
		return new form_group($iName, $iType);
		
	}
	
	/*
	 *	@method		bool		kijkt of een gegevens object al in het object opgenomen is
	 *	@param 		iNaam		string
	 *		
	*/
	
	private function elementExists($iName){
		
		$bool = false;
		
		foreach($this -> elements as $element){
				
			if($element -> getName() == $iName){
			
				$bool = true;
					
			}
		}
		return $bool;
		
	}
	
	public function setEncType($iType){
	
		$this -> enctype = $iType;
	
	}
	
	/*
	 *	@method		bool		kijkt het element type na alle elementen moeten van het type form_element zijn (deze klasse dus extenden)
	 *	@param 		iObj		object
	 *		
	*/
	
	private function checkElementType($iObj){
	
		if(isset($iObj) && is_object($iObj)){
		
			 if(get_class($iObj) == self::groupType || get_parent_class($iObj) == self::elementType){
					return true;
			}else{
				return false;
			}
			
		}else{
			return false;
		}
	
	}
	
	/*
		@method		string		produceert de html code voor het formulier inclusief die van al zijn elementen
	*/
	public function render(){
		
		$this -> action = $this -> action != NULL ?  $this -> action : $_SERVER['REQUEST_URI'];
		$this -> enctype = isset($this -> enctype) ?  $this -> enctype : self::MULTIPART_FRM_DATA;

	
		
		$class = self::decoratorPrefix.$this -> decorator;
		$file = get_include_path().'form/decorator/' . $this -> decorator.self::fileSuffix;
	
		
		if(is_file($file)){
			
			require_once($file);
			
			if(class_exists($class)){
		
				$decorator = new $class($this -> name, $this -> method, $this -> enctype, $this -> action);
				
			
			}else{
		
				throw new Exception("decorator doesn't exists");
			
			}
		}else{
		
			throw new Exception("decorator doesn't exists");
			
		}

		foreach($this -> elements as $element){
		
			$decorator -> addRow($element, $element -> getLabel());
					
		} 
		
		return $decorator -> render();
			
		
						
		
		
	
			
	
	}
	/*
		@method		bool		controleert of het gehele formulier gevalideert is
	*/
	public function isValid(){
		
		$bool = true;
	
		foreach($this -> elements as $element){
			
			if(get_class($element) == self::groupType){
				
				foreach($element -> getChilds() as $child){
					
					if(!$child -> isValid()){
					
						$bool = false;
						break;
					}
					
				}
			}else{
				if(!$element -> isValid()){
					
					$bool = false;
					
					break;
				}
			}
		}
		
		return $bool;
	}
	
	
	
	public function getErrors(){
		$errors = array();
		
		foreach($this -> elements as $element){
		
			foreach($element -> getErrors() as $error){
				$errors[] = $error;		
			}
		
		
		}
	
		return $errors;
	}
	

}	

// end class


?>